

#include "Tcp_Server.h"


Tcp_Server::Tcp_Server(Prngd_State state)
{

	create_socket = 0;
	new_socket = 0;
	temp_socket = 0;
	addrlen = 0;
	prngd = new Prngd(state);
	lfname = TCP_LOG;
	flog = true;

	address.sin_family = AF_INET;
	address.sin_addr.s_addr = INADDR_ANY;
	address.sin_port = htons(18200);
	work_thread_active = true;
	StartWorkerThread();
}


void Tcp_Server::thread_listen(pthread_t parent_th)
{
	char buffer[BUFFER_SIZE];
	int size = 0;
	worker_busy = false;
	memset(buffer, '\0', BUFFER_SIZE);


	while(listen_thread_active)
	{
		new_socket = accept( create_socket, (struct sockaddr*)&address, &addrlen);
		logTemp->append(" Client mit IP: ");
		logTemp->append(inet_ntoa(address.sin_addr));
		logTemp->append(" hat sich verbunden.");
		log((char*)logTemp->c_str());



		size = recv(new_socket, buffer, BUFFER_SIZE, 0);

		if(size > 0)
		{
			if(!worker_busy)
			{
				if(strcmp(buffer, "/exit") == 0)
				{
					listen_thread_active = false;
					log(" Sende SIGUSR2 an worker");
					pthread_kill(parent_th, SIGUSR2);
				}
				else
				{
					worker_busy = true;
					strncpy(work_buffer, buffer, BUFFER_SIZE);
					temp_socket = new_socket;
					log(" Sende SIGUSR1 an worker");
					pthread_kill(parent_th, SIGUSR1);
				}
				memset(buffer, '\0', BUFFER_SIZE);
			}
			else
			{
				log(" Client verbunden, aber Worker noch beschäftigt.");
				send(new_socket, "Server beschäftigt, bitte spaeter erneut versuchen.\n", 53, 0);
			}
		}
	}
	pthread_kill(parent_th, SIGPOLL);
}


void Tcp_Server::thread_work()
{
	char* result = NULL;
	int result_size = 0;
	active = true;
	int flag = 1;


	if((create_socket=socket(AF_INET, SOCK_STREAM,0)) > 0)
		log(" TCP Socket wurde angelegt.");

	setsockopt(create_socket, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));

	if(bind(create_socket, (struct sockaddr*)&address, sizeof(address)) != 0)
		log(" Port ist nicht frei !");

	listen(create_socket, 5);

	addrlen = sizeof(struct sockaddr_in);

	configSignals();

	while(work_thread_active)
	{
		param_count = 0;
		listen_thread_active= true;
		StartListenerThread((pthread_t)pthread_self());

		while(listen_thread_active)
		{
			sigwait(&sigmask, &sig);
			switch(sig)
			{
				case SIGUSR1:

					logTemp->append(" Client hat folgendes gesendet: ");
					logTemp->append(work_buffer, BUFFER_SIZE);
					log((char*)logTemp->c_str());

					//read all params from work_buffer and store them in a 2dim array like argv
					getParams();

					log(" Starte Erzeugung von Zufallsbits");

					//generate random bits and get the result size
					result = prngd->work(param_count, params);
					result_size = prngd->getResultSize();

					log(" Erzeugung von Zufallsbits beendet");
					//send result over tcp socket and close the tcp connection
					if(send(temp_socket, result, result_size, 0) > 0)
						log(" Zufallsbits an Client gesendet.");
					else
						log(" !Konnte Zufallsbits nicht übermitteln.");
					close(temp_socket);

					//clean up the param arrays and work_buffer
					deleteParams();
					memset(work_buffer, '\0', BUFFER_SIZE);
					worker_busy = false;

					break;

				case SIGUSR2:
					//Server got the command to shutdown
					listen_thread_active = false;
					work_thread_active = false;
					log(" /exit wurde empfangen, TCP Server wird heruntergefahren.");
					break;

				default:
					//client closed connection, but server will still run and wait for further clients
					listen_thread_active = false;
					work_thread_active = false;
					break;
			}
			param_count = 0;
		}

	}
	close(new_socket);
	close(create_socket);
	//wait for our listen_thread to be closed
	log(" Warte auf beenden von Listener");
	WaitForListenerThreadToExit();
	log(" Tcp Server beendet.");
	active = false;
}




